package com.ebeitech.camera;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.Size;
import android.os.Build;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;

public class QPICameraPreview extends ViewGroup implements
		SurfaceHolder.Callback {

	private final String TAG = "Preview";

	SurfaceView mSurfaceView;
	SurfaceHolder mHolder;
	Size mPreviewSize;
	Size mPictureSize;
	public List<Size> mSupportedPreviewSizes;
	public List<Size> mSupportedPictureSizes;
	Camera mCamera;

	private int cameraPosition = 1;//0代表前置摄像头，1代表后置摄像头

	public QPICameraPreview(Context context) {
		super(context);

		init(context);
	}

	public QPICameraPreview(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		// TODO Auto-generated constructor stub
		init(context);
	}

	public QPICameraPreview(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
		init(context);
	}

	private void init(Context context) {
		mSupportedPreviewSizes = new ArrayList<Camera.Size>();
		mSupportedPictureSizes = new ArrayList<Camera.Size>();
		mSurfaceView = new SurfaceView(context);
		addView(mSurfaceView);

		// Install a SurfaceHolder.Callback so we get notified when the
		// underlying surface is created and destroyed.
		mHolder = mSurfaceView.getHolder();
		mHolder.addCallback(this);
		mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
	}

	public void setCamera(Camera camera) {
		mCamera = camera;
		if (mCamera != null) {
			Parameters parameters = mCamera.getParameters();
			List<Size> supportedPreviewSizes = parameters.getSupportedPreviewSizes();
			List<Size> supportedPictureSizes = parameters.getSupportedPictureSizes();
			mSupportedPreviewSizes.clear();
			if (supportedPreviewSizes != null && supportedPreviewSizes.size() > 0) {
				mSupportedPreviewSizes.addAll(supportedPreviewSizes);
			}
			mSupportedPictureSizes.clear();
			if (supportedPictureSizes != null && supportedPictureSizes.size() > 0) {
				mSupportedPictureSizes.addAll(supportedPictureSizes);
			}
			//requestLayout();

			//sunjunli
			try {
				mCamera.setPreviewDisplay(mHolder);
			} catch (IOException exception) {
				Log.e(TAG, "IOException caused by setPreviewDisplay()",
						exception);
			}
		}
	}

	public void setPreviewSize() {
		LayoutParams params = mSurfaceView.getLayoutParams();
		if (params != null) {
			params.width = 200;
			params.height = 200;
			mSurfaceView.setLayoutParams(params);
		} else {
			Log.i("tiger log", "params is null");
		}

	}

	public void switchCamera(Camera camera) {
		if (camera != null) {
			setCamera(camera);
			try {
				camera.setPreviewDisplay(mHolder);
			} catch (IOException exception) {
				Log.e(TAG, "IOException caused by setPreviewDisplay()",
						exception);
			}
			/*Camera.Parameters parameters = camera.getParameters();
			parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
			parameters.setPictureSize(mPictureSize.width, mPictureSize.height);
			requestLayout();

			camera.setParameters(parameters);*/
			camera.startPreview();
		}
	}

	public SurfaceHolder getHolder(){
		return mHolder;
	}

	public void changeCamera() {
		//切换前后摄像头
		int cameraCount = 0;
		Camera.CameraInfo cameraInfo = null;
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
			cameraInfo = new Camera.CameraInfo();
		}
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
			cameraCount = Camera.getNumberOfCameras();//得到摄像头的个数
		}
		for(int i = 0; i < cameraCount; i++) {
			if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
				Camera.getCameraInfo(i, cameraInfo);//得到每一个摄像头的信息
			}
			if (cameraPosition == 1) {
				//现在是后置，变更为前置
				if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {//代表摄像头的方位，CAMERA_FACING_FRONT前置      CAMERA_FACING_BACK后置
					mCamera.setPreviewCallback(null);
					mCamera.stopPreview();//停掉原来摄像头的预览
					mCamera.release();//释放资源
					mCamera = null;//取消原来摄像头
					if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
						mCamera = Camera.open(i);//打开当前选中的摄像头
					}
					try {
						mCamera.setPreviewDisplay(mHolder);//通过surfaceview显示取景画面
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					mCamera.startPreview();//开始预览
					cameraPosition = 0;
					break;
				}
			} else {
				//现在是前置， 变更为后置
				if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {//代表摄像头的方位，CAMERA_FACING_FRONT前置      CAMERA_FACING_BACK后置
					mCamera.setPreviewCallback(null);
					mCamera.stopPreview();//停掉原来摄像头的预览
					mCamera.release();//释放资源
					mCamera = null;//取消原来摄像头
					if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
						mCamera = Camera.open(i);//打开当前选中的摄像头
					}
					try {
						mCamera.setPreviewDisplay(mHolder);//通过surfaceview显示取景画面
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					mCamera.startPreview();//开始预览
					cameraPosition = 1;
					break;
				}
			}
		}
	}


	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		// We purposely disregard child measurements because act as a
		// wrapper to a SurfaceView that centers the camera preview instead
		// of stretching it.
		final int width = resolveSize(getSuggestedMinimumWidth(),
				widthMeasureSpec);
		final int height = resolveSize(getSuggestedMinimumHeight(),
				heightMeasureSpec);
		setMeasuredDimension(width, height);

		/*if (mSupportedPreviewSizes != null) {
			mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width,
					height);
		}*/
		if (mCamera == null) {
			return;
		}
		try {
			mPreviewSize = mCamera.getParameters().getPreviewSize();
			mPictureSize = mCamera.getParameters().getPictureSize();
			Log.i(TAG, "onMeasure : mPreviewSize width = " + mPreviewSize.width + " , height = " + mPreviewSize.height);
			Log.i(TAG, "onMeasure : mPictureSize width = " + mPictureSize.width + " , height = " + mPictureSize.height);
		}catch (RuntimeException e){
			e.printStackTrace();
		}
	}

	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		if (mPreviewSize == null) {
			return;
		}

		//if (changed && getChildCount() > 0) {
		final View child = getChildAt(0);

		final int width = r - l;
		final int height = b - t;

			/*int previewWidth = width;
			int previewHeight = height;
			if (mPreviewSize != null) {
				previewWidth = mPreviewSize.width;
				previewHeight = mPreviewSize.height;
			}

			// Center the child SurfaceView within the parent.
			if (width * previewHeight > height * previewWidth) {
				final int scaledChildWidth = previewWidth * height
						/ previewHeight;
				child.layout((width - scaledChildWidth) / 2, 0,
						(width + scaledChildWidth) / 2, height);
			} else {
				final int scaledChildHeight = previewHeight * width
						/ previewWidth;
				child.layout(0, (height - scaledChildHeight) / 2, width,
						(height + scaledChildHeight) / 2);
			}*/

		//现在已经旋转了90度
		int previewWidth = mPreviewSize.height;
		int previewHeight = mPreviewSize.width;
		// Center the child SurfaceView within the parent.
		if (height * previewWidth > width * previewHeight) {
			final int scaledChildHeight = previewHeight * width
					/ previewWidth;
			child.layout(0, (height - scaledChildHeight) / 2, width,
					(height + scaledChildHeight) / 2);
		} else {
			final int scaledChildWidth = previewWidth * height
					/ previewHeight;
			child.layout((width - scaledChildWidth) / 2, 0,
					(width + scaledChildWidth) / 2, height);
		}
		Log.i(TAG, "onLayout : child layout width = " + child.getWidth() + " , height = " + child.getHeight());
		//}
	}

	public void surfaceCreated(SurfaceHolder holder) {
		// The Surface has been created, acquire the camera and tell it where
		// to draw.
		try {
			if (mCamera != null) {
				mCamera.setPreviewDisplay(holder);
			}
		} catch (IOException exception) {
			Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
		}
	}

	public void surfaceDestroyed(SurfaceHolder holder) {
		// Surface will be destroyed when we return, so stop the preview.
		if (mCamera != null) {
			/**
			 * 据说不调用会报Method called after release()异常
			 */
			mCamera.setPreviewCallback(null);
			mCamera.stopPreview();
		}
	}

	private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
		final double ASPECT_TOLERANCE = 0.1;
		double targetRatio = (double) w / h;
		if (sizes == null)
			return null;

		Size optimalSize = null;
		double minDiff = Double.MAX_VALUE;

		int targetHeight = h;

		// Try to find an size match aspect ratio and size
		for (Size size : sizes) {
			double ratio = (double) size.width / size.height;
			if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
				continue;
			if (Math.abs(size.height - targetHeight) < minDiff) {
				optimalSize = size;
				minDiff = Math.abs(size.height - targetHeight);
			}
		}

		// Cannot find the one match the aspect ratio, ignore the requirement
		if (optimalSize == null) {
			minDiff = Double.MAX_VALUE;
			for (Size size : sizes) {
				if (Math.abs(size.height - targetHeight) < minDiff) {
					optimalSize = size;
					minDiff = Math.abs(size.height - targetHeight);
				}
			}
		}
		return optimalSize;
	}

	public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
		// Now that the size is known, set up the camera parameters and begin
		// the preview.
		if (mCamera != null) {
			Camera.Parameters parameters = mCamera.getParameters();
			parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
			parameters.setPictureSize(mPictureSize.width, mPictureSize.height);
			requestLayout();
			mCamera.setParameters(parameters);
			try {
				mCamera.startPreview();
			} catch (Exception e){

			}
		}
	}

}
